package liming.tool.net;

import com.alibaba.dashscope.aigc.generation.GenerationParam;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.core.Timeout;
import liming.tool.json.FileConfig;
import liming.tool.json.ToJson;
import liming.tool.json.annotation.JsonMark;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.jetbrains.annotations.NotNull;

import java.io.IOException;
import java.time.Duration;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

public class NetServer {
    public static final String jsonRootName = "net-client-group";
    /**
     * 创建一个OkHttpClient实例，并设置超时时间、重试次数和拦截器
     * connectTimeout 连接超时时间，单位毫秒
     * readTimeout 读取超时时间，单位毫秒
     * writeTimeout 写入超时时间，单位毫秒
     * maxRetries 最大重试次数
     * initialTimeOut 初始重试间隔时间，单位毫秒
     */
    @JsonMark("okhttp")
    public static class OKHttpConfig implements ToJson {
        @JsonMark
        public int connectTimeout = 1000;
        @JsonMark
        public int readTimeout = 1000;
        @JsonMark
        public int writeTimeout = 1000;
        @JsonMark
        public int maxRetries = 3;
        @JsonMark
        public int initialTimeOut = 1000;
        OkHttpClient.Builder getBuilder() {
            return new OkHttpClient.Builder()
                    .connectTimeout(connectTimeout, java.util.concurrent.TimeUnit.MILLISECONDS)
                    .readTimeout(readTimeout, java.util.concurrent.TimeUnit.MILLISECONDS)
                    .writeTimeout(writeTimeout, java.util.concurrent.TimeUnit.MILLISECONDS)
                    .addInterceptor(new Interceptor(){
                        @NotNull
                        @Override
                        public Response intercept(@NotNull Chain chain) throws IOException {
                            Request request = chain.request();
                            AtomicInteger retryCount = new AtomicInteger(0);

                            while (true) {
                                try {
                                    Response response = chain.proceed(request);
                                    if (retryCount.get() > 0 && response.isSuccessful()) {
                                        System.out.println("重试成功，第 " + retryCount.get() + " 次重试");
                                    }
                                    return response;
                                } catch (IOException e) {
                                    if (retryCount.get() >= maxRetries
                                            || !isRetryableException(e)) {
                                        throw e;
                                    }

                                    long waitTime = (long) (initialTimeOut * Math.pow(2, retryCount.get()));
                                    System.out.println("请求失败，等待 " + waitTime + "ms 后重试 ("
                                            + (retryCount.get()+1) + "/" + maxRetries + ")");

                                    try {
                                        TimeUnit.MILLISECONDS.sleep(waitTime);
                                    } catch (InterruptedException ignored) {
                                        Thread.currentThread().interrupt();
                                    }
                                    retryCount.incrementAndGet();
                                }
                            }
                        }

                        private boolean isRetryableException(IOException e) {
                            // 可重试的异常类型：连接超时、读取超时等
                            return e instanceof java.net.SocketTimeoutException
                                    || e instanceof java.net.ConnectException;
                        }
                    });
        }

        public static OkHttpClient.Builder builder(String configName) {
            OKHttpConfig okHttpConfig = new OKHttpConfig();
            okHttpConfig.deserialize(FileConfig.getConfig(jsonRootName,configName));
            return okHttpConfig.getBuilder();
        }
        public static OkHttpClient.Builder builder() {
            OKHttpConfig okHttpConfig = new OKHttpConfig();
            FileConfig.getConfig(okHttpConfig,jsonRootName);
            return okHttpConfig.getBuilder();
        }
    }

    @JsonMark("openai")
    public static class OpenAIConfig implements ToJson{
        @JsonMark
        public int connectTimeout = 1000;
        @JsonMark
        public int readTimeout = 1000;
        @JsonMark
        public int writeTimeout = 1000;
        @JsonMark
        public String apikey;
        @JsonMark
        public String baseurl;
        OpenAIOkHttpClient.Builder getBuilder() {
            return new OpenAIOkHttpClient.Builder()
                    .timeout(new Timeout.Builder()
                            .connect(Duration.ofMillis(connectTimeout))
                            .read(Duration.ofMillis(readTimeout))
                            .write(Duration.ofMillis(writeTimeout))
                            .build())
                    .apiKey(apikey)
                    .baseUrl(baseurl);
        }
        public static OpenAIOkHttpClient.Builder builder(String configName) {
            OpenAIConfig openAIConfig = new OpenAIConfig();
            openAIConfig.deserialize(FileConfig.getConfig(jsonRootName,configName));
            return openAIConfig.getBuilder();
        }
        public static OpenAIOkHttpClient.Builder builder() {
            OpenAIConfig openAIConfig = new OpenAIConfig();
            FileConfig.getConfig(openAIConfig,jsonRootName);
            return openAIConfig.getBuilder();
        }
    }

    @JsonMark("dashscope")
    public static class DashScopeConfig implements ToJson {
        @JsonMark
        public String apiKey; // API Key
        @JsonMark
        public String model; // 模型名称，例如 "qwen-plus"

        /**
         * 获取 GenerationParam 的生成器
         * @return GenerationParam.Builder
         */
        public GenerationParam.GenerationParamBuilder<?, ?> getBuilder() {
            return GenerationParam.builder()
                    .apiKey(apiKey) // 设置 API Key
                    .model(model); // 设置模型名称
        }

        /**
         * 根据指定的配置名称创建 DashScopeConfig 的生成器
         *
         * @param configName 配置名称
         * @return DashScopeConfig.Builder
         */
        public static GenerationParam.GenerationParamBuilder<?, ?> builder(String configName) {
            DashScopeConfig dashScopeConfig = new DashScopeConfig();
            dashScopeConfig.deserialize(FileConfig.getConfig(jsonRootName, configName));
            return dashScopeConfig.getBuilder();
        }

        /**
         * 使用默认配置名称创建 DashScopeConfig 的生成器
         * @return DashScopeConfig.Builder
         */
        public static GenerationParam.GenerationParamBuilder<?, ?> builder() {
            DashScopeConfig dashScopeConfig = new DashScopeConfig();
            FileConfig.getConfig(dashScopeConfig,jsonRootName);
            return dashScopeConfig.getBuilder();
        }
    }

}
